﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace Apq.IO
{
	/// <summary>
	/// 已分块的本地文件缓存,所有块同用一个流对象
	/// </summary>
	public class FileCache
	{
		private string _FullFileName = string.Empty;
		/// <summary>
		/// 完整文件名,设置时打开文件流
		/// </summary>
		public string FullFileName
		{
			get { return _FullFileName; }
			set
			{
				// 先保证目标路径存在
				string strTargetPath = System.IO.Path.GetDirectoryName(value);
				if (!System.IO.Directory.Exists(strTargetPath))
				{
					System.IO.Directory.CreateDirectory(strTargetPath);
				}
				FS = new System.IO.FileStream(value, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);

				_FullFileName = value;
			}
		}
		/// <summary>
		/// 关联的文件流
		/// </summary>
		public System.IO.FileStream FS { get; set; }

		private List<FileSecCache> _FileSecCaches = new List<FileSecCache>();
		/// <summary>
		/// 缓存分块信息(至少一块)
		/// </summary>
		public List<FileSecCache> FileSecCaches
		{
			get
			{
				if (_FileSecCaches.Count < 1)
				{
					_FileSecCaches.Add(new FileSecCache(FullFileName, FS));
				}
				return _FileSecCaches;
			}
		}

		private List<FileSection> _FileSections = new List<FileSection>();
		/// <summary>
		/// 文件分块信息(由使用者确保至少含有一块)
		/// </summary>
		public List<FileSection> FileSections
		{
			get
			{
				return _FileSections;
			}
		}

		/// <summary>
		/// 默认构造函数,为成员赋予默认值
		/// </summary>
		private FileCache()
		{
		}

		/// <summary>
		/// 本地文件缓存区
		/// </summary>
		/// <param name="FullFileName">完整文件名</param>
		/// <param name="FileSections">分块缓存</param>
		public FileCache(string FullFileName, List<FileSection> FileSections)
			: this()
		{
			this.FullFileName = FullFileName;
			this._FileSections.AddRange(FileSections);

			CalcFileSecCaches();
		}

		/// <summary>
		/// 根据分块信息创建文件块的缓存区
		/// </summary>
		private void CalcFileSecCaches()
		{
			foreach (FileSection FileSection in FileSections)
			{
				FileSecCache fSecCache = new FileSecCache(FullFileName, FS, FileSection.PosBegin);
				_FileSecCaches.Add(fSecCache);
			}
		}

		/// <summary>
		/// 将所有未写入流的数据刷到流同时刷入文件系统
		/// </summary>
		public void Flush()
		{
			foreach (FileSecCache fsCache in FileSecCaches)
			{
				fsCache.FlushToStream();
			}

			FS.Flush();
		}
	}
}
